﻿--非战斗状态中允许shift+左键拖动玩家头像
local function UnitFramesPlus_PlayerShiftDrag()
    PlayerFrame:SetScript("OnMouseDown", function(self, elapsed)
        if UnitFramesPlusDB["player"]["movable"] == 1 then
            if IsShiftKeyDown() and (not InCombatLockdown()) then
                PlayerFrame:StartMoving();
                UnitFramesPlusVar["player"]["moving"] = 1;
            end
        end
    end)

    PlayerFrame:SetScript("OnMouseUp", function(self, elapsed)
        if UnitFramesPlusVar["player"]["moving"] == 1 then
            PlayerFrame:StopMovingOrSizing();
            UnitFramesPlusVar["player"]["moving"] = 0;
            UnitFramesPlusVar["player"]["moved"] = 1;
        end
    end)

    PlayerFrame:SetClampedToScreen(1);

    hooksecurefunc("PlayerFrame_ResetUserPlacedPosition", function()
        UnitFramesPlus_TargetPosition();
    end)
end

local function UnitFramesPlus_PlayerPosition()
    if UnitFramesPlusVar["player"]["moved"] == 0 then
        PlayerFrame:SetPoint("TOPLEFT", UIParent, "TOPLEFT", -19, -4);
    end
end

--精英头像
local UFP_PlayerTexture;
function UnitFramesPlus_PlayerDragon()
    if UnitFramesPlusDB["player"]["dragon"] == 1 then
        if UnitFramesPlusDB["player"]["raretype"] == 1 then
            UFP_PlayerTexture = "Interface\\TargetingFrame\\UI-TargetingFrame-Elite";
        elseif UnitFramesPlusDB["player"]["raretype"] == 2 then
            UFP_PlayerTexture = ("Interface\\TargetingFrame\\UI-TargetingFrame-Rare-Elite");
        elseif UnitFramesPlusDB["player"]["raretype"] == 3 then
            UFP_PlayerTexture = ("Interface\\TargetingFrame\\UI-TargetingFrame-Rare");
        end
    else
        UFP_PlayerTexture = ("Interface\\TargetingFrame\\UI-TargetingFrame");
    end
    PlayerFrameTexture:SetTexture(UFP_PlayerTexture);

    --设置扩展框素材与头像素材一致
    if UnitFramesPlusDB["player"]["extbar"] == 1 then
        UFP_PlayerExtBar:SetTexture(UFP_PlayerTexture);
    end
end

--头像缩放
local function UnitFramesPlus_PlayerFrameScaleSet(oldscale, newscale)
    local oldscale = oldscale or UnitFramesPlusDB["player"]["scale"];
    local newscale = newscale or UnitFramesPlusDB["player"]["scale"];
    local point, relativeTo, relativePoint, offsetX, offsetY = PlayerFrame:GetPoint();
    PlayerFrame:SetScale(newscale);
    PlayerFrame:ClearAllPoints();
    PlayerFrame:SetPoint(point, relativeTo, relativePoint, offsetX*oldscale/newscale, offsetY*oldscale/newscale);
    if UnitFramesPlusVar["target"]["moved"] == 0 then
        TargetFrame:ClearAllPoints();
        TargetFrame:SetPoint("TOPLEFT", PlayerFrame, "TOPRIGHT", 45+96*newscale, 0);
    end
    if UnitFramesPlusDB["player"]["portrait"] == 1 and UnitFramesPlusDB["player"]["ptype"] == 1 then
        UnitFramesPlus_PlayerPortraitDisplayUpdate();
    end
end

function UnitFramesPlus_PlayerFrameScale(oldscale, newscale)
    if not InCombatLockdown() then
        UnitFramesPlus_PlayerFrameScaleSet(oldscale, newscale);
    else
        local func = {};
        func.name = "UnitFramesPlus_PlayerFrameScaleSet";
        func.callback = function()
            UnitFramesPlus_PlayerFrameScaleSet(oldscale, newscale);            
        end;
        UnitFramesPlus_WaitforCall(func);
    end
end

--额外的生命值/法力值/生命值百分比
local PlayerHPMPPct = CreateFrame("Frame", "UFP_PlayerHPMPPct", PlayerFrame);
PlayerHPMPPct:SetFrameLevel(7);
PlayerHPMPPct.HP = PlayerHPMPPct:CreateFontString("UFP_PlayerHPMPPctHP", "OVERLAY", "TextStatusBarText");
PlayerHPMPPct.HP:SetFont(GameFontNormal:GetFont(), 12, "OUTLINE");
PlayerHPMPPct.HP:SetTextColor(1, 0.75, 0);
PlayerHPMPPct.HP:Hide();

PlayerHPMPPct.MP = PlayerHPMPPct:CreateFontString("UFP_PlayerHPMPPctMP", "OVERLAY", "TextStatusBarText");
PlayerHPMPPct.MP:SetFont(GameFontNormal:GetFont(), 12, "OUTLINE");
PlayerHPMPPct.MP:SetTextColor(1, 1, 1);
PlayerHPMPPct.MP:Hide();

PlayerHPMPPct.Pct = PlayerHPMPPct:CreateFontString("UFP_PlayerHPMPPctPct", "OVERLAY", "TextStatusBarText");
PlayerHPMPPct.Pct:SetFont(GameFontNormal:GetFont(), 12, "OUTLINE");
PlayerHPMPPct.Pct:SetTextColor(0, 1, 0);
PlayerHPMPPct.Pct:Hide();

--扩展框
local PlayerExtBar = PlayerFrame:CreateTexture("UFP_PlayerExtBar", "ARTWORK");
PlayerExtBar:Hide();

local PlayerExtBarBG = PlayerFrame:CreateTexture("UFP_PlayerExtBarBG", "BACKGROUND");
PlayerExtBarBG:Hide();

local fixforvehicle = CreateFrame("Frame");
function UnitFramesPlus_PlayerExtbar()
    UFP_PlayerExtBar:SetTexture(UFP_PlayerTexture);
    UFP_PlayerExtBar:SetWidth(138);
    UFP_PlayerExtBar:SetHeight(128);
    UFP_PlayerExtBar:SetTexCoord(0.3984375, 0, 0, 1);
    UFP_PlayerExtBar:ClearAllPoints();
    UFP_PlayerExtBar:SetPoint("TOPLEFT", PlayerFrame, "TOPLEFT", 226, 0);

    UFP_PlayerExtBarBG:SetTexture("Interface\\Tooltips\\UI-Tooltip-Background");
    UFP_PlayerExtBarBG:SetWidth(96);
    UFP_PlayerExtBarBG:SetHeight(42);
    UFP_PlayerExtBarBG:SetVertexColor(0, 0, 0, 0.5);
    UFP_PlayerExtBarBG:ClearAllPoints();
    UFP_PlayerExtBarBG:SetPoint("TOPLEFT", PlayerFrame, "TOPLEFT", 226, -23);
    if UnitFramesPlusDB["player"]["extbar"] == 1 then
        UFP_PlayerExtBar:Show();
        UFP_PlayerExtBarBG:Show();
        UFP_PlayerHPMPPct.HP:ClearAllPoints();
        UFP_PlayerHPMPPct.HP:SetPoint("CENTER", PlayerFrameHealthBar, "RIGHT", 53, -1);
        UFP_PlayerHPMPPct.HP:SetJustifyH("CENTER");
        UFP_PlayerHPMPPct.HP:Show();
        UFP_PlayerHPMPPct.MP:ClearAllPoints();
        UFP_PlayerHPMPPct.MP:SetPoint("CENTER", PlayerFrameManaBar, "RIGHT", 53, -1);
        UFP_PlayerHPMPPct.MP:SetJustifyH("CENTER");
        UFP_PlayerHPMPPct.MP:Show();
        UFP_PlayerHPMPPct.Pct:ClearAllPoints();
        UFP_PlayerHPMPPct.Pct:SetPoint("CENTER", PlayerFrameHealthBar, "RIGHT", 55, 14);
        UFP_PlayerHPMPPct.Pct:SetJustifyH("CENTER");
        UFP_PlayerHPMPPct.Pct:Show();

        --上载具后隐藏扩展框及扩展信息
        fixforvehicle:RegisterUnitEvent("UNIT_ENTERED_VEHICLE", "player");
        fixforvehicle:RegisterUnitEvent("UNIT_EXITED_VEHICLE", "player");
        fixforvehicle:SetScript("OnEvent", function(self, event, ...)
            if event == "UNIT_ENTERED_VEHICLE" then
                if UnitHasVehicleUI("player") then
                    UFP_PlayerExtBar:SetAlpha(0);
                    UFP_PlayerExtBarBG:SetAlpha(0);
                    UFP_PlayerHPMPPct.HP:SetAlpha(0);
                    UFP_PlayerHPMPPct.MP:SetAlpha(0);
                    UFP_PlayerHPMPPct.Pct:SetAlpha(0);
                end
            elseif event == "UNIT_EXITED_VEHICLE" then
                UFP_PlayerExtBar:SetAlpha(1);
                UFP_PlayerExtBarBG:SetAlpha(0.5);
                UFP_PlayerHPMPPct.HP:SetAlpha(1);
                UFP_PlayerHPMPPct.MP:SetAlpha(1);
                UFP_PlayerHPMPPct.Pct:SetAlpha(1);
            end;
        end)

        UnitFramesPlus_PlayerHealth();
        UnitFramesPlus_PlayerHPValueDisplayUpdate();
        UnitFramesPlus_PlayerPower();
        UnitFramesPlus_PlayerMPValueDisplayUpdate();
    else
        UFP_PlayerExtBar:Hide();
        UFP_PlayerExtBarBG:Hide();
        if fixforvehicle:IsEventRegistered("UNIT_ENTERED_VEHICLE") then
            fixforvehicle:UnregisterEvent("UNIT_ENTERED_VEHICLE");
            fixforvehicle:UnregisterEvent("UNIT_EXITED_VEHICLE");
            fixforvehicle:SetScript("OnEvent", nil);
        end
        UnitFramesPlus_PlayerHPMPPct();
    end
end

--隐藏扩展框后调整额外的生命值/法力值/生命值百分比的位置
function UnitFramesPlus_PlayerHPMPPct()
    if UnitFramesPlusDB["player"]["hpmp"] == 1 then
        UFP_PlayerHPMPPct.HP:ClearAllPoints();
        UFP_PlayerHPMPPct.HP:SetPoint("LEFT", PlayerFrameHealthBar, "RIGHT", 5, -1);
        UFP_PlayerHPMPPct.HP:SetJustifyH("LEFT");
        UFP_PlayerHPMPPct.HP:Show();
        UFP_PlayerHPMPPct.MP:ClearAllPoints();
        UFP_PlayerHPMPPct.MP:SetPoint("LEFT", PlayerFrameManaBar, "RIGHT", 5, -1);
        UFP_PlayerHPMPPct.MP:SetJustifyH("LEFT");
        UFP_PlayerHPMPPct.MP:Show();
        UFP_PlayerHPMPPct.Pct:ClearAllPoints();
        UFP_PlayerHPMPPct.Pct:SetPoint("LEFT", PlayerFrameHealthBar, "RIGHT", 5, 14);
        UFP_PlayerHPMPPct.Pct:SetJustifyH("LEFT");
        UFP_PlayerHPMPPct.Pct:Show();
    else
        UFP_PlayerHPMPPct.HP:Hide();
        UFP_PlayerHPMPPct.MP:Hide();
        UFP_PlayerHPMPPct.Pct:Hide();
    end
    UnitFramesPlus_PlayerHealth();
    UnitFramesPlus_PlayerHPValueDisplayUpdate();
    UnitFramesPlus_PlayerPower();
    UnitFramesPlus_PlayerMPValueDisplayUpdate();
end

--额外的生命值
local PlayerHealth = CreateFrame("Frame");
function UnitFramesPlus_PlayerHealth()
    if UnitFramesPlusDB["player"]["extbar"] == 0 and UnitFramesPlusDB["player"]["hpmp"] == 0 and UnitFramesPlusDB["player"]["pctonbar"] == 0 then
        if PlayerHealth:IsEventRegistered("PLAYER_ENTERING_WORLD") then
            PlayerHealth:UnregisterEvent("PLAYER_ENTERING_WORLD");
            PlayerHealth:UnregisterEvent("UNIT_HEALTH_FREQUENT");
            PlayerHealth:SetScript("OnEvent", nil);
        end
    else
        PlayerHealth:RegisterEvent("PLAYER_ENTERING_WORLD");
        PlayerHealth:RegisterUnitEvent("UNIT_HEALTH_FREQUENT", "player");
        PlayerHealth:SetScript("OnEvent", function(self, event, ...)
            UnitFramesPlus_PlayerHPValueDisplayUpdate();
        end)
    end
end

--刷新额外的生命值显示
function UnitFramesPlus_PlayerHPValueDisplayUpdate()
    local CurHP = UnitHealth("player");
    local MaxHP = UnitHealthMax("player");
    local CurHPfix, MaxHPfix = GetValueFix(CurHP, MaxHP, UnitFramesPlusDB["player"]["unit"]);
    local PctText = "";
    local PlayerExtHPText = "";

    if MaxHP > 0 then
        PctText = math.floor(100*CurHP/MaxHP).."%";
    end

    if UnitFramesPlusDB["player"]["extbar"] == 1 or UnitFramesPlusDB["player"]["hpmp"] == 1 then
        if UnitFramesPlusDB["player"]["hpmppartone"] == 1 then
            PlayerExtHPText = CurHPfix;
        elseif UnitFramesPlusDB["player"]["hpmppartone"] == 2 then
            PlayerExtHPText = MaxHPfix;
        elseif UnitFramesPlusDB["player"]["hpmppartone"] == 3 then
            PlayerExtHPText = PctText;
        end

        if UnitFramesPlusDB["player"]["hpmpparttwo"] == 1 then
            PlayerExtHPText = PlayerExtHPText.."/"..CurHPfix;
        elseif UnitFramesPlusDB["player"]["hpmpparttwo"] == 2 then
            PlayerExtHPText = PlayerExtHPText.."/"..MaxHPfix;
        elseif UnitFramesPlusDB["player"]["hpmpparttwo"] == 3 then
            PlayerExtHPText = PlayerExtHPText.."/"..PctText;
        end

        UFP_PlayerHPMPPct.HP:SetText(PlayerExtHPText);

        if UnitFramesPlusDB["player"]["hpmppartone"] == 3 or UnitFramesPlusDB["player"]["hpmpparttwo"] == 3 then
            if UnitFramesPlusDB["player"]["coord"] == 0 then
                UFP_PlayerHPMPPct.Pct:SetText("");
            end
        else
            local _, instanceType = IsInInstance();
            if (UnitFramesPlusDB["player"]["coord"] == 0) 
                or (instanceType ~= "none" and UnitFramesPlusDB["player"]["coord"] == 1 and UnitFramesPlusDB["player"]["coordpct"] == 1) then
                UFP_PlayerHPMPPct.Pct:SetText(PctText);
            end
        end
    end
end

--玩家坐标
local coord = CreateFrame("Frame");
local x, y;
function UnitFramesPlus_PlayerCoordinate()
    if UnitFramesPlusDB["player"]["coord"] == 1 then
        coord:RegisterEvent("ZONE_CHANGED");
        coord:RegisterEvent("ZONE_CHANGED_INDOORS");
        coord:RegisterEvent("ZONE_CHANGED_NEW_AREA");
        coord:SetScript("OnEvent", function(self, event)
            UnitFramesPlus_PlayerCoordinateDisplayUpdate();
        end)

        coord:SetScript("OnUpdate", function(self, elapsed)
            self.timer = (self.timer or 0) + elapsed;
            if self.timer >= 0.3 then
                UnitFramesPlus_PlayerCoordinateDisplayUpdate();
                self.timer = 0;
            end
        end)
    else
        if coord:IsEventRegistered("ZONE_CHANGED") then
            coord:UnregisterEvent("ZONE_CHANGED");
            coord:UnregisterEvent("ZONE_CHANGED_INDOORS");
            coord:UnregisterEvent("ZONE_CHANGED_NEW_AREA");
            coord:SetScript("OnEvent", nil);
            coord:SetScript("OnUpdate", nil);
        end
    end
end

function UnitFramesPlus_PlayerCoordinateDisplayUpdate()
    local _, instanceType = IsInInstance();
    if instanceType ~= "none" and UnitFramesPlusDB["player"]["coord"] == 1 and UnitFramesPlusDB["player"]["coordpct"] == 1 then
        return;
    end

    local x, y = GetPlayerMapPosition("player");
    if x ~= 0 or y ~= 0 then
        UFP_PlayerHPMPPct.Pct:SetText(format("(%.0f, %.0f)", x*100, y*100));
    else
        if WorldMapFrame:IsShown() == false then
            SetMapToCurrentZone();
            x, y = GetPlayerMapPosition("player");
            UFP_PlayerHPMPPct.Pct:SetText(format("(%.0f, %.0f)", x*100, y*100));
        else
            UFP_PlayerHPMPPct.Pct:SetText("");
        end
    end
end

--额外的法力值/能量等
local PlayerPower = CreateFrame("Frame");
function UnitFramesPlus_PlayerPower()
    if UnitFramesPlusDB["player"]["extbar"] == 0 and UnitFramesPlusDB["player"]["hpmp"] == 0 then
        if PlayerPower:IsEventRegistered("UNIT_POWER") then
            PlayerPower:UnregisterEvent("PLAYER_ENTERING_WORLD");
            PlayerPower:UnregisterEvent("UNIT_POWER");
            PlayerPower:SetScript("OnEvent", nil);
        end
    else
        PlayerPower:RegisterEvent("PLAYER_ENTERING_WORLD");
        PlayerPower:RegisterUnitEvent("UNIT_POWER", "player");
        PlayerPower:SetScript("OnEvent", function(self, event, ...)
            UnitFramesPlus_PlayerMPValueDisplayUpdate();
        end)
    end
end

--刷新额外的法力值/能量等显示
function UnitFramesPlus_PlayerMPValueDisplayUpdate()
    local CurMP = UnitPower("player");
    local MaxMP = UnitPowerMax("player");
    local CurMPfix, MaxMPfix = GetValueFix(CurMP, MaxMP, UnitFramesPlusDB["player"]["unit"]);
    local PctText = "";
    local powerType = UnitPowerType("player");

    if powerType == 0 then
        if MaxMP > 0 then
            PctText = math.floor(100*CurMP/MaxMP).."%";
        end
    else
        PctText = CurMP;
        -- PctText == 0 then PctText = "" end
    end

    if UnitFramesPlusDB["player"]["extbar"] == 1 or UnitFramesPlusDB["player"]["hpmp"] == 1 then
        if UnitFramesPlusDB["player"]["hpmppartone"] == 1 then
            PlayerExtMPText = CurMPfix;
        elseif UnitFramesPlusDB["player"]["hpmppartone"] == 2 then
            PlayerExtMPText = MaxMPfix;
        elseif UnitFramesPlusDB["player"]["hpmppartone"] == 3 then
            PlayerExtMPText = PctText;
        end

        if UnitFramesPlusDB["player"]["hpmpparttwo"] == 1 then
            PlayerExtMPText = PlayerExtMPText.."/"..CurMPfix;
        elseif UnitFramesPlusDB["player"]["hpmpparttwo"] == 2 then
            PlayerExtMPText = PlayerExtMPText.."/"..MaxMPfix;
        elseif UnitFramesPlusDB["player"]["hpmpparttwo"] == 3 then
            PlayerExtMPText = PlayerExtMPText.."/"..PctText;
        end

        UFP_PlayerHPMPPct.MP:SetText(PlayerExtMPText);
    end
end

--格式化数值显示
function GetValueFix(valueCurr, valueMax, valueunit)
    local valueCurrfix, valueMaxfix, unitbig, unitsmall;
    local unittype = UnitFramesPlusDB["player"]["unittype"];
    if valueunit == 0 then
        valueCurrfix = valueCurr;
        valueMaxfix = valueMax;
    elseif valueunit == 1 and unittype == 2 and (GetLocale() == "zhCN" or GetLocale() == "zhTW") then
        if GetLocale() == "zhCN" then
            unitbig = "亿";
            unitsmall = "万";
        elseif GetLocale() == "zhTW" then
            unitbig = "億";
            unitsmall = "萬";
        end
        if valueCurr >= 100000000 then
            valueCurrfix = math.floor(valueCurr/100000000)..unitbig;
        elseif valueCurr >= 100000 then
            valueCurrfix = math.floor(valueCurr/10000)..unitsmall;
        else
            valueCurrfix = valueCurr;
        end

        if valueMax >= 100000000 then
            valueMaxfix = math.floor(valueCurr/100000000)..unitbig;
        elseif valueMax >= 100000 then
            valueMaxfix = math.floor(valueMax/10000)..unitsmall;
        else
            valueMaxfix = valueMax;
        end
    else
        unitbig = "M";
        unitsmall = "K";
        if valueCurr >= 10000000 then
            valueCurrfix = math.floor(valueCurr/1000000)..unitbig;
        elseif valueCurr >= 10000 then
            valueCurrfix = math.floor(valueCurr/1000)..unitsmall;
        else
            valueCurrfix = valueCurr;
        end

        if valueMax >= 10000000 then
            valueMaxfix = math.floor(valueCurr/1000000)..unitbig;
        elseif valueMax >= 10000 then
            valueMaxfix = math.floor(valueMax/1000)..unitsmall;
        else
            valueMaxfix = valueMax;
        end
    end
    return valueCurrfix, valueMaxfix;
end

--玩家生命条染色
local chb = CreateFrame("Frame");
function UnitFramesPlus_PlayerColorHPBar()
    if UnitFramesPlusDB["player"]["colorhp"] == 1 then
        if UnitFramesPlusDB["player"]["colortype"] == 1 then
            PlayerFrameHealthBar:SetScript("OnValueChanged", nil);
            chb:RegisterEvent("PLAYER_ENTERING_WORLD");
            chb:RegisterUnitEvent("UNIT_ENTERED_VEHICLE", "player");
            chb:RegisterUnitEvent("UNIT_EXITED_VEHICLE", "player");
            chb:SetScript("OnEvent", function(self, event, ...)
                UnitFramesPlus_PlayerColorHPBarDisplayUpdate();
            end)
        elseif UnitFramesPlusDB["player"]["colortype"] == 2 then
            if chb:IsEventRegistered("PLAYER_ENTERING_WORLD") then
                chb:UnregisterEvent("PLAYER_ENTERING_WORLD");
                chb:UnregisterEvent("UNIT_ENTERED_VEHICLE");
                chb:UnregisterEvent("UNIT_EXITED_VEHICLE");
                chb:SetScript("OnEvent", nil);
            end
            PlayerFrameHealthBar:SetScript("OnValueChanged", function(self, value)
                UnitFramesPlus_PlayerColorHPBarDisplayUpdate();
            end)
        end
        --PlayerFrameHealthBar.lockColor = true;
    else
        PlayerFrameHealthBar:SetScript("OnValueChanged", nil);
        if chb:IsEventRegistered("PLAYER_ENTERING_WORLD") then
            chb:UnregisterEvent("PLAYER_ENTERING_WORLD");
            chb:UnregisterEvent("UNIT_ENTERED_VEHICLE");
            chb:UnregisterEvent("UNIT_EXITED_VEHICLE");
            chb:SetScript("OnEvent", nil);
        end
        PlayerFrameHealthBar:SetStatusBarColor(0, 1, 0);
        --PlayerFrameHealthBar.lockColor = nil;
    end
end

--刷新玩家生命条染色显示
function UnitFramesPlus_PlayerColorHPBarDisplayUpdate()
    if UnitFramesPlusDB["player"]["colorhp"] == 1 then
        if UnitFramesPlusDB["player"]["colortype"] == 1 then
            local HealthBarColor = RAID_CLASS_COLORS[select(2, UnitClass("player"))] or {r=0, g=1, b=0};
            if UnitHasVehicleUI("player") then HealthBarColor = {r=0, g=1, b=0} end
            PlayerFrameHealthBar:SetStatusBarColor(HealthBarColor.r, HealthBarColor.g, HealthBarColor.b);
        elseif UnitFramesPlusDB["player"]["colortype"] == 2 then
            local CurHP = UnitHealth("player");
            local MaxHP = UnitHealthMax("player");
            local Pct = math.floor(100*CurHP/MaxHP)/100;
            local r, g, b = 0, 1, 0;
            if Pct > 0.5 then
                r = (1.0-Pct)*2;
                g = 1.0;
            else
                r = 1.0;
                g = Pct*2;
            end
            if r < 0 then r = 0 end
            if g < 0 then g = 0 end
            if r > 1 then r = 1 end
            if g > 1 then g = 1 end
            PlayerFrameHealthBar:SetStatusBarColor(r, g, b);
        end
    end
end

--玩家头像内战斗信息
function UnitFramesPlus_PlayerPortraitIndicator()
    local registered = PlayerFrame:IsEventRegistered("UNIT_COMBAT");
    if UnitFramesPlusDB["player"]["indicator"] == 1 then
        if not registered then
            PlayerFrame:RegisterUnitEvent("UNIT_COMBAT", "player", "vehicle");
        end
    else
        if registered then
            PlayerFrame:UnregisterEvent("UNIT_COMBAT");
        end
    end
end

--玩家头像类型
local Player3DPortrait = CreateFrame("PlayerModel", "UFP_Player3DPortrait", PlayerFrame);
Player3DPortrait:SetWidth(51);
Player3DPortrait:SetHeight(51);
Player3DPortrait:SetFrameLevel(1);
Player3DPortrait:ClearAllPoints();
Player3DPortrait:SetPoint("CENTER", PlayerPortrait, "CENTER", 0, -1);
Player3DPortrait:Hide();
Player3DPortrait.Background = Player3DPortrait:CreateTexture("UFP_Player3DPortraitBG", "BACKGROUND");
Player3DPortrait.Background:SetTexture("Interface\\AddOns\\UnitFramesPlus\\Portrait3D");
Player3DPortrait.Background:SetWidth(64);
Player3DPortrait.Background:SetHeight(64);
Player3DPortrait.Background:ClearAllPoints();
Player3DPortrait.Background:SetPoint("CENTER", Player3DPortrait, "CENTER", 0, 0);
Player3DPortrait.Background:Hide();

local PlayerClassPortrait = PlayerFrame:CreateTexture("UFP_PlayerClassPortrait", "ARTWORK");
PlayerClassPortrait:SetWidth(64);
PlayerClassPortrait:SetHeight(64);
PlayerClassPortrait:ClearAllPoints();
PlayerClassPortrait:SetPoint("TOPLEFT", PlayerFrame, "TOPLEFT", 42, -12);
PlayerClassPortrait:Hide();

local ppt = CreateFrame("Frame");
function UnitFramesPlus_PlayerPortrait()
    if UnitFramesPlusDB["player"]["portrait"] == 1 then
        PlayerPortrait:Hide();
        if UnitFramesPlusDB["player"]["ptype"] == 1 then
            UFP_Player3DPortrait:Show();
            UFP_PlayerClassPortrait:Hide();
            ppt:RegisterEvent("PLAYER_ENTERING_WORLD");
            ppt:RegisterEvent("PLAYER_DEAD");
            ppt:RegisterEvent("PLAYER_ALIVE");
            ppt:RegisterEvent("PLAYER_UNGHOST");
            ppt:RegisterUnitEvent("UNIT_MODEL_CHANGED", "player");
            ppt:RegisterUnitEvent("UNIT_ENTERED_VEHICLE", "player");
            ppt:RegisterUnitEvent("UNIT_EXITED_VEHICLE", "player");
            ppt:SetScript("OnEvent", function(self, event, ...)
                if event == "PLAYER_ENTERING_WORLD" then
                    if UnitFramesPlusDB["player"]["p3dbg"] == 1 then
                        local color = RAID_CLASS_COLORS[select(2, UnitClass("player"))] or NORMAL_FONT_COLOR;
                        UFP_Player3DPortrait.Background:SetVertexColor(color.r/1.5, color.g/1.5, color.b/1.5, 1);
                    end
                    UnitFramesPlus_PlayerPortraitDisplayUpdate();
                elseif event == "UNIT_MODEL_CHANGED" or event == "UNIT_EXITED_VEHICLE" then
                    UnitFramesPlus_PlayerPortraitDisplayUpdate();
                elseif event == "PLAYER_DEAD" then
                    UFP_Player3DPortrait:SetLight(true, false, 0, 0, 0, 1.0, 1, 0.3, 0.3);
                elseif event == "PLAYER_ALIVE" then
                    if UnitIsGhost("player") then
                        UFP_Player3DPortrait:SetLight(true, false, 0, 0, 0, 1.0, 0.25, 0.25, 0.25);
                    else
                        UFP_Player3DPortrait:SetLight(true, false, 0, 0, 0, 1.0, 1, 1, 1);
                    end
                elseif event == "PLAYER_UNGHOST" then
                    UFP_Player3DPortrait:SetLight(true, false, 0, 0, 0, 1.0, 1, 1, 1);
                elseif event == "UNIT_ENTERED_VEHICLE" and UnitHasVehicleUI("player") then
                    UFP_Player3DPortrait:SetPortraitZoom(1);
                    UFP_Player3DPortrait:ClearModel();
                    UFP_Player3DPortrait:SetUnit("vehicle");
                end
            end)
        elseif UnitFramesPlusDB["player"]["ptype"] == 2 then
            UFP_Player3DPortrait:Hide();
            UFP_PlayerClassPortrait:Show();
            if ppt:IsEventRegistered("PLAYER_ENTERING_WORLD") then
                ppt:UnregisterEvent("PLAYER_ENTERING_WORLD");
                ppt:UnregisterEvent("PLAYER_DEAD");
                ppt:UnregisterEvent("PLAYER_ALIVE");
                ppt:UnregisterEvent("PLAYER_UNGHOST");
                ppt:UnregisterEvent("UNIT_MODEL_CHANGED");
                ppt:UnregisterEvent("UNIT_ENTERED_VEHICLE");
                ppt:UnregisterEvent("UNIT_EXITED_VEHICLE");
                ppt:SetScript("OnEvent", nil);
            end
        end
        UnitFramesPlus_PlayerPortraitDisplayUpdate();
        UnitFramesPlus_PlayerPortrait3DBGDisplayUpdate();
    else
        PlayerPortrait:Show();
        UFP_Player3DPortrait:Hide();
        UFP_PlayerClassPortrait:Hide();
        if ppt:IsEventRegistered("PLAYER_ENTERING_WORLD") then
            ppt:UnregisterEvent("PLAYER_ENTERING_WORLD");
            ppt:UnregisterEvent("PLAYER_DEAD");
            ppt:UnregisterEvent("PLAYER_ALIVE");
            ppt:UnregisterEvent("PLAYER_UNGHOST");
            ppt:UnregisterEvent("UNIT_MODEL_CHANGED");
            ppt:UnregisterEvent("UNIT_ENTERED_VEHICLE");
            ppt:UnregisterEvent("UNIT_EXITED_VEHICLE");
            ppt:SetScript("OnEvent", nil);
        end
    end
end

--刷新玩家头像显示
function UnitFramesPlus_PlayerPortraitDisplayUpdate()
    if UnitFramesPlusDB["player"]["ptype"] == 1 then
        UFP_Player3DPortrait:Show();
        UFP_Player3DPortrait:SetPortraitZoom(1);
        UFP_Player3DPortrait:ClearModel();
        UFP_Player3DPortrait:SetUnit("player");
        if UnitIsGhost("player") then
            UFP_Player3DPortrait:SetLight(true, false, 0, 0, 0, 1.0, 0.25, 0.25, 0.25);
        elseif UnitIsDead("player") then
            UFP_Player3DPortrait:SetLight(true, false, 0, 0, 0, 1.0, 1, 0.3, 0.3);
        else
            UFP_Player3DPortrait:SetLight(true, false, 0, 0, 0, 1.0, 1, 1, 1);
        end
    elseif UnitFramesPlusDB["player"]["ptype"] == 2 then
        local IconCoord = CLASS_ICON_TCOORDS[select(2,UnitClass("player"))];
        if IconCoord then
            UFP_PlayerClassPortrait:SetTexture("Interface\\TargetingFrame\\UI-Classes-Circles");
            UFP_PlayerClassPortrait:SetTexCoord(unpack(IconCoord));
        end
    end
end

--刷新玩家3D头像背景显示
function UnitFramesPlus_PlayerPortrait3DBGDisplayUpdate()
    if UnitFramesPlusDB["player"]["portrait"] == 1 
    and UnitFramesPlusDB["player"]["ptype"] == 1
    and UnitFramesPlusDB["player"]["p3dbg"] == 1 then
        UFP_Player3DPortrait.Background:Show();
    else
        UFP_Player3DPortrait.Background:Hide();
    end
end

--玩家头像自动隐藏
local fah = CreateFrame("Frame");
function UnitFramesPlus_PlayerFrameAutohide()
    if UnitFramesPlusDB["player"]["autohide"] == 1 then
        fah:RegisterEvent("PLAYER_ENTERING_WORLD");
        fah:RegisterEvent("PLAYER_TARGET_CHANGED");
        fah:RegisterEvent("PLAYER_REGEN_ENABLED");
        fah:RegisterEvent("PLAYER_REGEN_DISABLED");
        fah:RegisterUnitEvent("UNIT_POWER", "player");
        fah:RegisterUnitEvent("UNIT_MAXPOWER", "player");
        fah:RegisterUnitEvent("UNIT_HEALTH", "player");
        fah:RegisterUnitEvent("UNIT_MAXHEALTH", "player");
        fah:RegisterUnitEvent("UNIT_ENTERED_VEHICLE", "player");
        fah:RegisterUnitEvent("UNIT_EXITED_VEHICLE", "player");
        fah:SetScript("OnEvent", function(self, event, ...)
            if event == "PLAYER_ENTERING_WORLD" or event == "PLAYER_TARGET_CHANGED"
                or event == "PLAYER_REGEN_ENABLED" or event == "UNIT_EXITED_VEHICLE"
                or event == "UNIT_POWER" or event == "UNIT_MAXPOWER"
                or event == "UNIT_HEALTH" or event == "UNIT_MAXHEALTH" then
                UnitFramesPlus_PlayerFrameAutohideDisplayUpdate();
            elseif event == "PLAYER_REGEN_DISABLED" or event == "UNIT_ENTERED_VEHICLE" then
                PlayerFrame:SetAlpha(1);
            end
        end)
    else
        if fah:IsEventRegistered("PLAYER_ENTERING_WORLD") then
            fah:UnregisterEvent("PLAYER_ENTERING_WORLD");
            fah:UnregisterEvent("PLAYER_TARGET_CHANGED");
            fah:UnregisterEvent("PLAYER_REGEN_ENABLED");
            fah:UnregisterEvent("PLAYER_REGEN_DISABLED");
            fah:UnregisterEvent("UNIT_POWER");
            fah:UnregisterEvent("UNIT_MAXPOWER");
            fah:UnregisterEvent("UNIT_HEALTH");
            fah:UnregisterEvent("UNIT_MAXHEALTH");
            fah:UnregisterEvent("UNIT_ENTERED_VEHICLE");
            fah:UnregisterEvent("UNIT_EXITED_VEHICLE");
            fah:SetScript("OnEvent", nil);
            UnitFramesPlus_PlayerFrameAutohideDisplayUpdate();
        end
    end
end

function UnitFramesPlus_PlayerFrameAutohideDisplayUpdate()
    if not InCombatLockdown() then
        if UnitFramesPlusDB["player"]["autohide"] == 1 then
            local powertypr = UnitPowerType("player");
            if (( powertypr == 0 or powertypr == 2 or powertypr == 3 ) and UnitPower("player") ~= UnitPowerMax("player"))
                or (( powertypr == 1 or powertypr == 6 ) and UnitPower("player") ~= 0)
                or (UnitHealth("player") ~= UnitHealthMax("player"))
                or UnitExists("target") then
                PlayerFrame:SetAlpha(1);
                return;
            end
            PlayerFrame:SetAlpha(0);
        else
            PlayerFrame:SetAlpha(1);
        end
    end
end

--鼠标移过时才显示数值
function UnitFramesPlus_PlayerBarTextMouseShow()
    if UnitFramesPlusDB["player"]["mouseshow"] == 1 then
        PlayerFrameHealthBarText:SetAlpha(0);
        PlayerFrameHealthBarTextLeft:SetAlpha(0);
        PlayerFrameHealthBarTextRight:SetAlpha(0);
        PlayerFrameHealthBar:SetScript("OnEnter",function(self)
            PlayerFrameHealthBarText:SetAlpha(1);
            PlayerFrameHealthBarTextLeft:SetAlpha(1);
            PlayerFrameHealthBarTextRight:SetAlpha(1);
        end);
        PlayerFrameHealthBar:SetScript("OnLeave",function()
            PlayerFrameHealthBarText:SetAlpha(0);
            PlayerFrameHealthBarTextLeft:SetAlpha(0);
            PlayerFrameHealthBarTextRight:SetAlpha(0);
        end);
        PlayerFrameManaBarText:SetAlpha(0);
        PlayerFrameManaBarTextLeft:SetAlpha(0);
        PlayerFrameManaBarTextRight:SetAlpha(0);
        PlayerFrameManaBar:SetScript("OnEnter",function(self)
            PlayerFrameManaBarText:SetAlpha(1);
            PlayerFrameManaBarTextLeft:SetAlpha(1);
            PlayerFrameManaBarTextRight:SetAlpha(1);
        end);
        PlayerFrameManaBar:SetScript("OnLeave",function()
            PlayerFrameManaBarText:SetAlpha(0);
            PlayerFrameManaBarTextLeft:SetAlpha(0);
            PlayerFrameManaBarTextRight:SetAlpha(0);
        end);
        PlayerFrameAlternateManaBarText:SetAlpha(0);
        PlayerFrameAlternateManaBar.LeftText:SetAlpha(0);
        PlayerFrameAlternateManaBar.RightText:SetAlpha(0);
        PlayerFrameAlternateManaBar:SetScript("OnEnter",function(self)
            PlayerFrameAlternateManaBarText:SetAlpha(1);
            PlayerFrameAlternateManaBar.LeftText:SetAlpha(1);
            PlayerFrameAlternateManaBar.RightText:SetAlpha(1);
        end);
        PlayerFrameAlternateManaBar:SetScript("OnLeave",function()
            PlayerFrameAlternateManaBarText:SetAlpha(0);
            PlayerFrameAlternateManaBar.LeftText:SetAlpha(0);
            PlayerFrameAlternateManaBar.RightText:SetAlpha(0);
        end);
    else
        PlayerFrameHealthBarText:SetAlpha(1);
        PlayerFrameHealthBarTextLeft:SetAlpha(1);
        PlayerFrameHealthBarTextRight:SetAlpha(1);
        PlayerFrameHealthBar:SetScript("OnEnter",nil);
        PlayerFrameHealthBar:SetScript("OnLeave",nil);
        PlayerFrameManaBarText:SetAlpha(1);
        PlayerFrameManaBarTextLeft:SetAlpha(1);
        PlayerFrameManaBarTextRight:SetAlpha(1);
        PlayerFrameManaBar:SetScript("OnEnter",nil);
        PlayerFrameManaBar:SetScript("OnLeave",nil);
        PlayerFrameAlternateManaBarText:SetAlpha(1);
        PlayerFrameAlternateManaBar.LeftText:SetAlpha(1);
        PlayerFrameAlternateManaBar.RightText:SetAlpha(1);
        PlayerFrameAlternateManaBar:SetScript("OnEnter",nil);
        PlayerFrameAlternateManaBar:SetScript("OnLeave",nil);
    end
end

--模块初始化
function UnitFramesPlus_PlayerInit()
    UnitFramesPlus_PlayerShiftDrag();
    UnitFramesPlus_PlayerDragon();
    UnitFramesPlus_PlayerExtbar();
    UnitFramesPlus_PlayerColorHPBar();
    UnitFramesPlus_PlayerPortraitIndicator();
    UnitFramesPlus_PlayerPortrait();
    UnitFramesPlus_PlayerCoordinate();
    UnitFramesPlus_PlayerFrameScale();
    UnitFramesPlus_PlayerFrameAutohide();
    UnitFramesPlus_PlayerBarTextMouseShow();
end

function UnitFramesPlus_PlayerLayout()
    UnitFramesPlus_PlayerPosition();
end